home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
dev
/
c
/
vbcc.lha
/
vbcc
/
loop.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-31
|
61KB
|
1,580 lines
/* $VER: vbcc (loop.c) V0.4 */
/* schleifenorientierte Optimierungen */
#include "opt.h"
static char FILE_[]=__FILE__;
#define MOVE_IC 1
#define MOVE_COMP 2
/* Liste, in die ICs eingetragen werden, die aus Schleifen */
/* gezogen werden sollen. */
struct movlist{
struct movlist *next;
struct IC *IC;
struct flowgraph *target_fg;
int flags;
};
struct movlist *first_mov,*last_mov;
int report_weird_code,report_suspicious_loops;
/* Bitvektoren fuer schleifeninvariante ICs */
unsigned char *invariant,*inloop,*moved,*moved_completely;
unsigned char *fg_tmp;
unsigned char *not_movable;
size_t bsize;
/* Liste, in die ICs fuer strength-reduction eingetragen */
/* werden. */
struct srlist{
struct srlist *next;
struct IC *ind_var;
struct IC *IC;
struct flowgraph *target_fg;
/* Hilfsvariable, falls eine aequivalente Operation schon reduziert */
/* wurde. */
struct Var *hv;
};
struct srlist *first_sr,*last_sr;
/* Liste, in die Daten fuer loop-unrolling eingetragen werden. */
struct urlist{
int flags;
long total,unroll;
struct IC *cmp,*branch,*ind;
struct flowgraph *start,*head;
struct urlist *next;
} *first_ur;
#define UNROLL_COMPLETELY 1
#define UNROLL_MODULO 2
#define UNROLL_INVARIANT 3
/* Hier werden Induktionsvariablen vermerkt */
struct IC **ind_vars;
static struct flowgraph *first_fg;
int loops(struct flowgraph *fg,int footers)
/* kennzeichnet Schleifen im Flussgraph; wenn footers!=0 werden darf eine */
/* Schleife nur einen gemeinsamen Austrittspunkt haben */
{
int i,start,end,c=0;struct flowlist *lp;struct flowgraph *g,*loopend;
if(DEBUG&1024) printf("searching loops\n");
g=fg;
while(g){
start=g->index;
end=-1;
for(lp=g->in;lp;lp=lp->next){
if(!lp->graph) continue;
if(lp->graph->branchout==g||!lp->graph->end||lp->graph->end->code!=BRA){
i=lp->graph->index;
if(i>=start&&i>end){ end=i;loopend=lp->graph; }
}
}
if(end>=0){
/* Schleife oder etwas aehnliches */
struct flowgraph *p=g;
if(DEBUG&1024) printf("found possible loop from blocks %d to %d\n",start,end);
if(1/*goto_used*/){
if(DEBUG&1024) printf("have to check...\n");
do{
if(!p||p->index>end) break;
/* testen, ob aus der Schleife gesprungen wird */
if(p->branchout&&footers){
i=p->branchout->index;
if(i<start){
end=-1;
break;
}
if(i>end&&(DEBUG&1024)){
puts("jump out of loop");
if(p->branchout!=loopend->normalout){
puts("no break");
if(p->branchout->start->typf!=return_label) puts("no return");
}
}
if(i>end&&p->branchout!=loopend->normalout&&p->branchout->start->typf!=return_label){
/* Sprung zu anderem als dem normalen Austritt oder return */
end=-1;
break;
}
}
/* testen, ob in die Schleife gesprungen wird */
if(p!=g){
for(lp=p->in;lp;lp=lp->next){
if(!lp->graph) continue;
if(lp->graph->branchout==p){
i=lp->graph->index;
if(i<start){
if(report_weird_code){error(175);report_weird_code=0;}
end=-1;
break;
}
if(i>end){
end=-1;
break;
}
}
}
}
if(p->index==end) break;
p=p->normalout;
}while(end>=0);
}else{
if(DEBUG&1024) printf("must be a loop, because there was no goto\n");
}
}
if(end>=0){
if(DEBUG&1024) printf("confirmed that it is a loop\n");
g->loopend=loopend;
c++;
}
g=g->normalout;
}
return(c);
}
struct flowgraph *create_loop_headers(struct flowgraph *fg,int av)
/* Fuegt vor jede Schleife einen Kopf-Block ein, wenn noetig. */
/* Wenn av!=0 werden aktive Variablen korrekt uebertragen und */
/* diverse Registerlisten uebernommen und index=-1 gesetzt. */
/* Kann einen Block mehrmals in der ->in Liste eintragen */
{
struct flowgraph *g,*last,*new,*rg=fg;
struct IC *lic,*lastic;
if(DEBUG&1024) printf("creating loop-headers\n");
g=fg;last=0;lastic=0;
while(g){
new=0;
if(g->loopend){
if(!last){
struct flowlist *lp;
new=mymalloc(sizeof(struct flowgraph));
rg=new;
new->in=0;
new->start=new->end=0;
lp=mymalloc(sizeof(struct flowlist));
lp->graph=new;
lp->next=g->in;
g->in=lp;
}else{
struct flowlist *lp,*nl,**ls;
new=mymalloc(sizeof(struct flowgraph));
last->normalout=new;
lic=mymalloc(ICS);
lic->line=0;
lic->file=0;
new->start=new->end=lic;
lic->code=LABEL;
lic->typf=++label;
lic->q1.flags=lic->q2.flags=lic->z.flags=0;
lic->q1.am=lic->q2.am=lic->z.am=0;
lic->use_cnt=lic->change_cnt=0;
lic->use_list=lic->change_list=0;
if(lastic) lastic->next=lic;
else first_ic=lic;
lic->prev=lastic;
g->start->prev=lic;
lic->next=g->start;
lp=g->in;ls=&new->in;
while(lp){
if(lp->graph&&lp->graph->index<g->index){
/* Eintritt von oben soll in den Kopf */
nl=mymalloc(sizeof(struct flowlist));
nl->graph=lp->graph;
nl->next=0;
(*ls)=nl;
ls=&nl->next;
if(lp->graph->branchout==g){
struct IC *p=lp->graph->end;
if(DEBUG&1024) printf("changing branch\n");
while(p&&p->code==FREEREG) p=p->prev;
if(!p||p->code<BEQ||p->code>BRA) ierror(0);
p->typf=lic->typf;
lp->graph->branchout=new;
}
lp->graph=new;
}
lp=lp->next;
}
if(!new->in) ierror(0);
}
if(new){
if(DEBUG&1024) printf("must insert loop-header before block %d\n",g->index);
basic_blocks++;
new->branchout=0;
new->loopend=0;
if(av)
new->index=-1;
else
new->index=basic_blocks;
new->normalout=g;
new->calls=0;
new->loop_calls=0;
new->rd_in=new->rd_out=new->rd_kill=new->rd_gen=0;
new->ae_in=new->ae_out=new->ae_kill=new->ae_gen=0;
new->cp_in=new->cp_out=new->cp_kill=new->cp_gen=0;
if(!av){
new->av_in=new->av_out=new->av_kill=new->av_gen=0;
}else{
new->av_in=mymalloc(vsize);
new->av_out=mymalloc(vsiz